﻿using LostOrFind.Context;
using LostOrFind.Models;
using Microsoft.EntityFrameworkCore;

namespace LostOrFind.Repositories.Impl;

public class OccasionRepository: IOccasionRepository
{
    private MyDbContext _context;

    public OccasionRepository(MyDbContext context)
    {
        _context = context;
    }
    public int AddOccasion(Occasion occasion)
    {
        using var transaction = _context.Database.BeginTransaction();
        try
        {
            _context.Occasions.Add(occasion);
            var result = _context.SaveChanges();
            transaction.Commit();
            return result;
        }
        catch (Exception)
        {
            transaction.Rollback();
            throw;
        }
    }

    public int DeleteOccasion(int occasionId,string userName)
    {
        using var transaction = _context.Database.BeginTransaction();
        try
        {
            var occasionToDelete = _context.Occasions
                .Include(d=>d.User)
                .FirstOrDefault(o=>o.Id == occasionId);
            
            if (occasionToDelete != null)
            {
                if (occasionToDelete.User!.Name != userName)
                {
                    throw new UnauthorizedAccessException();
                }
                _context.Occasions.Remove(occasionToDelete);
                int result = _context.SaveChanges();
                transaction.Commit();
                return result;
            }

            // Handle the case where the occasion with the given ID does not exist
            return -1;
        }
        catch (Exception)
        {
            transaction.Rollback();
            throw;
        }
    }

    public int UpdateOccasion(Occasion occasion)
    {
        using var transaction = _context.Database.BeginTransaction();
        try
        {
            var dbOccasion = _context.Occasions.Include(o => o.User)
                .Include(o => o.Status)
                .Include(o => o.Location)
                .Include(o => o.Category)
                .FirstOrDefault(o => o.Id == occasion.Id);
            if (dbOccasion == null)
            {
                _context.Occasions.Add(occasion);
            }
            else
            {
                dbOccasion.Description = occasion.Description;
                dbOccasion.Contact = occasion.Contact;
                dbOccasion.Lost = occasion.Lost;

                // Update foreign key properties
                dbOccasion.UserId = occasion.UserId;
                dbOccasion.StatusId = occasion.StatusId;
                dbOccasion.LocationId = occasion.LocationId;
                dbOccasion.CategoryId = occasion.CategoryId;
            }
            var result = _context.SaveChanges();
            transaction.Commit();
            return result;
        }
        catch(Exception)
        { 
            transaction.Rollback(); 
            throw; 
        }
    }

   public Occasion? GetOccasionById(int occasionId) 
   { 
       return _context.Occasions
           .Include(o=>o.Category)
           .Include(o=>o.Location)
           .Include(o=>o.Status)
           .Include(o=>o.User)
           .FirstOrDefault(o => o.Id == occasionId); 
   }

   public IList<Occasion> GetOccasionByUserId(int userId)
   {
       return _context.Occasions
           .Include(o => o.Category)
           .Include(o => o.Location)
           .Include(o => o.Status)
           .Include(o => o.User)
           .Where(o=>o.UserId==userId)
           .ToList();
   }

   public IList<Occasion> GetOccasionByRange(int from, int to,bool lost) 
   { 
       return _context.Occasions.Where(o => o.Id >= from && o.Id <= to)
           .Include(o=>o.Category)
           .Include(o=>o.Location)
           .Include(o=>o.Status)
           .Where(o=>o.Lost==lost).ToList(); 
   } 
}